package de.tudarmstadt.gdi1.project;

import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import de.tudarmstadt.gdi1.project.alphabet.Alphabet;
import de.tudarmstadt.gdi1.project.alphabet.Distribution;
import de.tudarmstadt.gdi1.project.substitution.CipherUtils;

/**
 * 
 * The implementation of the Distribution Interface
 * 
 * @author Christopher Hammel
 * @version 0.1
 * 
 */

public class FrequencyDistribution implements Distribution {

	private LinkedHashMap<String,Double> relFrequency; 
	private Alphabet alphabet; // The given Alphabet
	private String strSourceString; // The encrypted String
	private String strNormalizedString;
	CipherUtils u = new CipherUtils();
	Map<Integer, List<String>> ngrams;

	/**
	 * Creates a new FrequencyDistribution Object and saves how often every
	 * Element of a given alphabet is present in given Text
	 * 
	 * @param source
	 *            The alphabet to be used by this Class
	 * @param text
	 *            The encrypted Source Text
	 * @param ngramsize
	 *            Ignored for now!
	 * @return void
	 * 
	 */

	public FrequencyDistribution(Alphabet source, String text, int ngramsize) {
		strSourceString = text;
		alphabet = source;
		strNormalizedString = alphabet.normalize(strSourceString);
		relFrequency = new LinkedHashMap<String, Double>(); 
		int[] ngram = new int[ngramsize];
		for (int i = 0; i < ngramsize; i++){
			ngram[i] = i+1;
		}
		ngrams = u.ngramize(strNormalizedString, ngram);
		for (List<String> l : ngrams.values()){
			for(String s : l){
				relFrequency.put(s, getFrequency(s));				
			}
		}
	}

	@Override
	public List<String> getSorted(int length) {
		LinkedList<String> sortedList = new LinkedList<String>();
			for (String s : relFrequency.keySet()){
				if((s.length() == length)){
					sortedList.add(s);
				}
			}		
			Collections.sort(sortedList, new Comparator<String>() {
				@Override
				public int compare(String o1, String o2) {
					if(relFrequency.get(o1) < relFrequency.get(o2)) return 1;
					if(relFrequency.get(o1) > relFrequency.get(o2)) return -1;
					return 0;
				}
			});
		return sortedList;
	}


	@Override
	public double getFrequency(String key) {
		double len = strNormalizedString.length();
		int iCount = 0;
		if (len != 0) {
			for (int i = 0; i >= 0; i = strNormalizedString.indexOf(key, i) + 1) {
				if (strNormalizedString.indexOf(key, i) >= 0) {
					iCount++;
				}else{
					break;
				}
			}
			return iCount/(len - (key.length() - 1));
		} else
			return 0;
	}

	/**
	 * Returns the Alphabet used by this Object
	 * 
	 * @return The Alphabet
	 * 
	 */

	@Override
	public Alphabet getAlphabet() {
		return alphabet;
	}

	/**
	 * Ignored for now!
	 */

	@Override
	public String getByRank(int length, int rank) {
		String s = getSorted(length).get(rank-1);
		return s;
	}

}
